import React, { useEffect, useState, useMemo } from "react";
import classNames from "classnames";
import type { PageListItemProps, RenderType, PaginationProps } from "./type";
import {
  PageItem,
  PageJump,
  PageArrow,
  PageInput,
  PageTotal,
  PageSizeOptions,
} from "./components";
import { calculatePageList, getPages } from "./misc";
import {
  JUMP_NUM,
  prefixCls,
  DEFAULT_PAGE_NUM,
  DEFAULT_PAGE_SIZE,
} from "./constant";

const options = [10, 20, 50, 100];

const Pagination: React.VFC<PaginationProps> = (props) => {
  const {
    defaultCurrent = DEFAULT_PAGE_NUM,
    defaultPageSize = DEFAULT_PAGE_SIZE,
    current = defaultCurrent,
    pageSize = defaultPageSize,
    total,
    onChange,
    mini = false,
  } = props;

  const [currentPage, setCurrentPage] = useState<number>(
    current || defaultCurrent
  );
  const [currentPageSize, setCurrentPageSize] = useState<number>(
    pageSize || defaultPageSize
  );
  const onNextPage = () => {
    setCurrentPage(currentPage + 1);
  };

  const onPrevPage = () => {
    setCurrentPage(currentPage - 1);
  };

  const pages = useMemo(
    () => getPages(total, currentPageSize),
    [total, currentPageSize]
  );

  const onJumpPrev = () => {
    if (currentPage - JUMP_NUM < 1) {
      setCurrentPage(1);
    } else {
      setCurrentPage(currentPage - JUMP_NUM);
    }
  };

  const onJumpNext = () => {
    if (currentPage + JUMP_NUM > pages) {
      setCurrentPage(pages);
    } else {
      setCurrentPage(currentPage + JUMP_NUM);
    }
  };

  const pageList = useMemo(() => {
    let list = calculatePageList(total, currentPage, currentPageSize).map(
      (page: PageListItemProps<RenderType>) => {
        if (page.type === "page") {
          let p = page as PageListItemProps<"page">;
          return (
            <PageItem
              key={`${p.pageNum}+${p.active}`}
              page={p.pageNum}
              active={p.active}
              onClick={setCurrentPage}
            />
          );
        } else {
          let p = page as PageListItemProps<"jump">;
          return (
            <PageJump
              key={`jump-${p.direction}`}
              jumpNumber={p.jumpNum}
              direction={p.direction}
              onClick={p.direction === "prev" ? onJumpPrev : onJumpNext}
            />
          );
        }
      }
    );
    list.unshift(
      <PageArrow
        key={`${prefixCls}-prev`}
        direction="prev"
        disabled={currentPage == 1}
        onClick={onPrevPage}
      />
    );
    list.push(
      <PageArrow
        key={`${prefixCls}-next`}
        direction="next"
        disabled={currentPage == pages}
        onClick={onNextPage}
      />
    );
    return list;
  }, [total, currentPage, currentPageSize]);

  const onOk = (page: number) => {
    if (page > pages) {
      setCurrentPage(pages);
    } else if (page == 0) {
      setCurrentPage(1);
    } else {
      setCurrentPage(page);
    }
  };

  const onPagesChanged = (pages: number) => {
    if (currentPage > pages) {
      setCurrentPage(pages);
    }
  };

  useEffect(() => {
    setCurrentPageSize(pageSize);
  }, [pageSize]);
  useEffect(() => {
    setCurrentPage(current);
  }, [current]);
  useEffect(() => {
    onPagesChanged(pages);
  }, [pages]);

  useEffect(() => {
    onChange && onChange(currentPage, currentPageSize);
  }, [currentPage, currentPageSize]);

  if (mini) {
    return (
      <div className={prefixCls}>
        <ul>
          <PageArrow
            key={`${prefixCls}-prev`}
            direction="prev"
            disabled={currentPage == 1}
            onClick={onPrevPage}
          />
          <PageInput onOk={onOk} mini={mini} page={currentPage} max={pages} />
          <div
            className={classNames(
              `${prefixCls}-item`,
              `${prefixCls}-item-mini`
            )}
          >
            /
          </div>
          <div
            className={classNames(
              `${prefixCls}-item`,
              `${prefixCls}-item-mini`
            )}
          >
            {pages}
          </div>
          <PageArrow
            key={`${prefixCls}-next`}
            direction="next"
            disabled={currentPage == pages}
            onClick={onNextPage}
          />
        </ul>
      </div>
    );
  }

  return (
    <div className={prefixCls}>
      <ul>
        <PageTotal key="total" total={total} />
        <PageSizeOptions
          options={options.map((option) => ({
            label: `${option} 条/页`,
            value: option.toString(),
          }))}
          value={currentPageSize}
          onChange={setCurrentPageSize}
        />
        {pageList}
        {pages > 1 && <PageInput key="input" onOk={onOk} max={pages} />}
      </ul>
    </div>
  );
};

export default Pagination;
